package com.cmsz.collection.config;

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author liupeng
 * @date 2020/1/9
 * @description
 */
@Configuration
@Component
@ConditionalOnClass(value = {RestTemplate.class,CloseableHttpClient.class})
public class HttpClientConfig {
    @Value("${spring.http.client.pool.maxTotal}")
    private Integer maxTotal;

    @Value("${spring.http.client.pool.defaultMaxPerRoute}")
    private Integer defaultMaxPerRoute;

    @Value("${spring.http.client.pool.connectTimeout}")
    private Integer connectTimeout;

    @Value("${spring.http.client.pool.connectionRequestTimeout}")
    private Integer connectionRequestTimeout;

    @Value("${spring.http.client.pool.socketTimeout}")
    private Integer socketTimeout;

    @Value("${spring.http.client.pool.validateAfterInactivity}")
    private Integer validateAfterInactivity;

    @Bean(name = "httpClientTemplate")
    public RestTemplate restTemplate() {
        RestTemplate restTemplate =  new RestTemplate(httpRequestFactory());
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();

        HttpMessageConverter<?> messageConverter = null;
        for (HttpMessageConverter<?> item:messageConverters) {
            if (StringHttpMessageConverter.class == item.getClass()){
                messageConverter = item;
                break;
            }
        }
        if (null != messageConverter){
            messageConverters.remove(messageConverter);
        }

        messageConverters.add(1,new StringHttpMessageConverter(StandardCharsets.UTF_8));

        return restTemplate;
    }

    @Bean
    public ClientHttpRequestFactory httpRequestFactory(){
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

    @Bean
    public HttpClient httpClient(){
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(maxTotal);
        connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
        connectionManager.setValidateAfterInactivity(validateAfterInactivity);

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(socketTimeout)
                .setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .build();

        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
    }
}
